﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using System.Collections;

namespace SchemaMonitor.json
{
    [DataContract]
    public class CFieldPointer : CField
    {
        //Data
        [DataMember(Order = 1)]
        public List<Guid> Refs;

		//Constructor
		public CFieldPointer(CNodeBasic parent, CTag tag, CNode n) : this(parent, tag, n.NodeGuid) { }
        public CFieldPointer(CNodeBasic parent, CTag tag, Guid g) : base(parent, tag)
        {
            this.Value = g;
        }
		public CFieldPointer(CNodeBasic parent, CTag tag, CNodeList list) : this(parent, tag, list.Ids) { }
        public CFieldPointer(CNodeBasic parent, CTag tag, List<Guid> values) : base(parent, tag)
        {
            this.Refs = values;
        }
        public CFieldPointer(CNodeBasic parent, CTag tag, Dictionary<string, object> i, CUser c) : this(parent, tag, CNodeRoot.PersistJson(tag.FieldType, i,c)) { }
        public CFieldPointer(CNodeBasic parent, CTag tag, object[] array, CUser c)               : base(parent, tag)
        {
            var pointers = new List<Guid>(array.Length);
            foreach (Dictionary<string, object> i in array)
            {
                var n = CNodeRoot.PersistJson(tag.FieldType, i, c);
                pointers.Add(n.NodeGuid);
            }

            this.Refs = pointers;
        }

        //Serialisation Constructors
        private CFieldPointer() { }
        static CFieldPointer() {  ProtoBuf.Serializer.PrepareSerializer<CFieldPointer>(); }

        //Custom
        public CNodeRoot Get(CNodeRootList data)
        {
            return GetNode(data).Root;
        }
        public CNodeRoot Get(CNodeList data)
        {
            return GetNode(data).Root;
        }
        public CNode GetNode(CNodeRootList data)
        {
            return GetNode(data.Known);
        }

        public CNodeList GetNodes(CNodeList known)
        {
            object[] arr = Values;
			if (null == arr)
				return new CNodeList(0);
            var list = new CNodeList(arr.Length);
            foreach (Guid i in arr)
                list.Add(GetNode_DbOrCache(known, i));
            return list;
        }
        public CNode GetNode(CNodeList known)
		{
			var list = GetNodes(known);
			if (list.Count == 0)
				return null;
			return list[0];
		}

        private CNode GetNode_DbOrCache(CNodeList known, Guid r)
        {
            var n = known.GetById(r);
            if (null != n)
                return n;

            n = new CNode().GetById(r, true);
            if (n != null)
                known.Add(n);
            return n;
        }

        //Must Override
        public override IList List { get { return Refs; } set { Refs = value.Cast<Guid>().ToList(); } }
        protected override IList InitList() { return new List<Guid>(); }
        protected override IList InitList(object[] array) { return array.Cast<Guid>().ToList(); }
    }
}
